/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package webServices;

import dao.reponse.DaoAbstractReponseLocal;
import entities.Proposition;
import entities.question.AbstractQuestion;
import entities.question.QuestionOuverte;
import entities.questionnaire.Questionnaire;
import entities.reponse.AbstractReponse;
import entities.reponse.ReponseChoix;
import entities.reponse.ReponseLibre;
import entities.utilisateur.AbstractRepondant;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.EJB;
import javax.jws.WebService;
import javax.ejb.Stateless;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 *
 * @author aurelien.emery
 */
@WebService(endpointInterface = "webServices.ReponseQuestionnaire")
@Stateless()
public class ReponseQuestionnaireBean {

    @EJB
    private DaoAbstractReponseLocal daoReponse;

    /**
     * Web service d extraction des donnees
     */
    public String getReponses() {

        List<AbstractReponse> rep = daoReponse.findAll();
        // organisation et tri des differentes reponses en vue de la construction du xml
        Map<Questionnaire, Map<AbstractRepondant, Map<AbstractQuestion, List<AbstractReponse>>>> donnees = formatReponse(daoReponse.findAll());

        // creation du document XML
        Document document = getDocument(donnees);
        // formatage du document en String
        String result = formatXML(document.getFirstChild(), 0);

        return result;
    }

    /**
     * Methode permettant de trier les reponses pour le formattage xml
     * l emploi de liste de reponse permet de gerer les reponses multiples du repondant anonyme
     */
    private Map<Questionnaire, Map<AbstractRepondant, Map<AbstractQuestion, List<AbstractReponse>>>> formatReponse(List<AbstractReponse> reponses) {
        Map<Questionnaire, Map<AbstractRepondant, Map<AbstractQuestion, List<AbstractReponse>>>> result = new HashMap<Questionnaire, Map<AbstractRepondant, Map<AbstractQuestion, List<AbstractReponse>>>>();
        for (AbstractReponse r : reponses) {
            //  daoReponse.detach(r);

            // creation de l entree de questionnaire
            if (!result.containsKey(r.getQuestionnaire())) {
                result.put(r.getQuestionnaire(), new HashMap<AbstractRepondant, Map<AbstractQuestion, List<AbstractReponse>>>());
            }

            // creation de l entree de repondant
            if (!result.get(r.getQuestionnaire()).containsKey(r.getRepondant())) {
                result.get(r.getQuestionnaire()).put(r.getRepondant(), new HashMap<AbstractQuestion, List<AbstractReponse>>());
            }

            // creation de l entree de question
            if (!result.get(r.getQuestionnaire()).get(r.getRepondant()).containsKey(r.getQuestion())) {
                result.get(r.getQuestionnaire()).get(r.getRepondant()).put(r.getQuestion(), new ArrayList<AbstractReponse>());
            }

            // ajout de la reponse dans l entree designée
            result.get(r.getQuestionnaire()).get(r.getRepondant()).get(r.getQuestion()).add(r);
        }

        return result;
    }

    /**
     * Renvoie une chaine de caractere correspondant au contenu du noeud XML
     */
    private String formatXML(Node node, int decalageNoeud) {
        if (node == null) {
            System.out.println("noeud null");
            return null;
        }
        StringBuffer result = new StringBuffer();
        if (node.hasAttributes()) {
            result.append(decalage(decalageNoeud));
            result.append("<");
            result.append(node.getNodeName());
            for (int i = 0; i < node.getAttributes().getLength(); i++) {
                result.append(" ");
                result.append(node.getAttributes().item(i).getNodeName());
                result.append("=\"");
                result.append(node.getAttributes().item(i).getNodeValue());
                result.append("\"");
            }
            result.append(">\n");
            if (node.getChildNodes().getLength() > 0) {
                for (int i = 0; i < node.getChildNodes().getLength(); i++) {
                    result.append(formatXML(node.getChildNodes().item(i), decalageNoeud + 1));
                }
            } 
            result.append(decalage(decalageNoeud));
            result.append("</");
            result.append(node.getNodeName());
            result.append(">\n");
        }

        return result.toString();
    }

    /**
     * Cette methode permet de generer un document XML a partir de la liste de reponses passée en parametre.
     *
     */
    private Document getDocument(Map<Questionnaire, Map<AbstractRepondant, Map<AbstractQuestion, List<AbstractReponse>>>> donnees) {
        Document document = null;
        DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
        try {
            // le try/catch est necesaire pour l instruction ci-dessous
            DocumentBuilder constructeur = fabrique.newDocumentBuilder();
            document = constructeur.newDocument();

            SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy");
            // creation du 1er niveau : racine
            Element racine = document.createElement("export");
            racine.setAttribute("date", dateFormatter.format(new GregorianCalendar().getTime()));
            document.appendChild(racine);
            for (Questionnaire q : donnees.keySet()) {
                // creation de 2eme niveau : questionnaire
                Element questionnaire = document.createElement("questionnaire");
                questionnaire.setAttribute("id", Long.toString(q.getId()));
                questionnaire.setAttribute("nom", q.getNom());
                racine.appendChild(questionnaire);
                // creation des 3eme niveau : repondant
                for (AbstractRepondant r : donnees.get(q).keySet()) {
                    Element repondant = document.createElement("repondant");
                    repondant.setAttribute("nom", r.getNom());
                    repondant.setAttribute("prenom", r.getPrenom());
                    questionnaire.appendChild(repondant);
                    // creation des 4eme niveau : question
                    for (AbstractQuestion q1 : donnees.get(q).get(r).keySet()) {
                        Element question = document.createElement("question");
                        question.setAttribute("intitule", q1.getIntitule());
                        repondant.appendChild(question);
                        //creation des 5eme niveau : reponse
                        if (q1.getClass().equals(QuestionOuverte.class)) {
                            for (AbstractReponse r1 : donnees.get(q).get(r).get(q1)) {
                                Element reponse = document.createElement("reponse");
                                reponse.setAttribute("valeur", ((ReponseLibre) r1).getReponse());
                                question.appendChild(reponse);
                            }
                        } else {
                            for (AbstractReponse r11 : donnees.get(q).get(r).get(q1)) {
                                ReponseChoix r1 = (ReponseChoix) r11;
                                for (Proposition p : r1.getListPropositionChoisies()) {
                                    Element reponse = document.createElement("reponse");
                                    reponse.setAttribute("valeur", p.getValeur());
                                    reponse.setAttribute("texte", p.getTexte());
                                    // reponse.setTextContent(p.getTexte());
                                    question.appendChild(reponse);
                                }
                            }
                        }
                    }
                }
            }
        } catch (ParserConfigurationException e) {
            System.out.println("erreur ParserConfigurationException");
            return null;
        }
        return document;
    }

    private StringBuffer decalage(int decalage) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < decalage; i++) {
            result.append("\t");
        }
        return result;
    }
}
